package com.dyz.controller;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.json.JSONUtil;
import com.dyz.model.BucketPolicyConfigDto;
import com.dyz.model.MinioConfigProperties;
import com.dyz.model.MinioUploadDto;
import com.dyz.model.Result;
import io.minio.*;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import java.text.SimpleDateFormat;
import java.util.Date;


@RestController
@RequestMapping("/file")
@Api(tags = "文件管理")
@Slf4j
public class FileController {
    @Resource
    private MinioConfigProperties minioConfigProperties;
    @ApiOperation("文件上传")
    @PostMapping("/upload")
    public Result<?> upload(@RequestPart("file") MultipartFile file) {
        try {
            //创建一个MinIO的Java客户端
            MinioClient minioClient =MinioClient.builder()
                    .endpoint(minioConfigProperties.getEndpoint())
                    .credentials(minioConfigProperties.getAccessKey(),minioConfigProperties.getSecretKey())
                    .build();
            //判断存储桶是否已经存在
            boolean isExist = minioClient.bucketExists(BucketExistsArgs.builder().bucket(minioConfigProperties.getBucketName()).build());
            if (isExist) {
                log.info("存储桶已经存在！");
            } else {
                //创建存储桶并设置只读权限
                minioClient.makeBucket(MakeBucketArgs.builder().bucket(minioConfigProperties.getBucketName()).build());
                BucketPolicyConfigDto bucketPolicyConfigDto = createBucketPolicyConfigDto(minioConfigProperties.getBucketName());
                SetBucketPolicyArgs setBucketPolicyArgs = SetBucketPolicyArgs.builder()
                        .bucket(minioConfigProperties.getBucketName())
                        .config(JSONUtil.toJsonStr(bucketPolicyConfigDto))
                        .build();
                minioClient.setBucketPolicy(setBucketPolicyArgs);
            }
            String filename = file.getOriginalFilename();
            SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd");
            // 设置存储对象名称
            String objectName = sdf.format(new Date()) + "/" + filename;
            // 使用putObject上传一个文件到存储桶中
            PutObjectArgs putObjectArgs = PutObjectArgs.builder()
                    .bucket(minioConfigProperties.getBucketName())
                    .object(objectName)
                    .contentType(file.getContentType())
                    .stream(file.getInputStream(), file.getSize(), ObjectWriteArgs.MIN_MULTIPART_SIZE).build();
            minioClient.putObject(putObjectArgs);
            log.info("文件上传成功!");
            MinioUploadDto minioUploadDto = new MinioUploadDto();
            minioUploadDto.setName(filename);
            minioUploadDto.setUrl(minioConfigProperties.getEndpoint() + "/" + minioConfigProperties.getBucketName() + "/" + objectName);
            return Result.success(minioUploadDto);
        } catch (Exception e) {
            e.printStackTrace();
            log.info("上传发生错误: {}！", e.getMessage());
        }
        return Result.fail("上传文件失败");
    }

    /**
     * 创建存储桶的访问策略，设置为只读权限
     */
    private BucketPolicyConfigDto createBucketPolicyConfigDto(String bucketName) {
        BucketPolicyConfigDto.Statement statement = BucketPolicyConfigDto.Statement.builder()
                .Effect("Allow")
                .Principal("*")
                .Action("s3:GetObject")
                .Resource("arn:aws:s3:::"+bucketName+"/*.**").build();
        return BucketPolicyConfigDto.builder()
                .Version("2012-10-17")
                .Statement(CollUtil.toList(statement))
                .build();
    }

    @ApiOperation("文件删除")
    @PostMapping(value = "/delete")
    public Result<?> delete(@RequestParam("objectName") String objectName) {
        try {
            MinioClient minioClient = MinioClient.builder()
                    .endpoint(minioConfigProperties.getEndpoint())
                    .credentials(minioConfigProperties.getAccessKey(),minioConfigProperties.getSecretKey())
                    .build();
            minioClient.removeObject(RemoveObjectArgs.builder().bucket(minioConfigProperties.getBucketName()).object(objectName).build());
            return Result.success(null);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return Result.fail("删除失败");
    }
}
